package com.yh.csx.event.common.utils;

import com.yh.csx.event.common.exception.EventException;
import com.yh.csx.event.common.exception.ExceptionEnum;
import lombok.extern.slf4j.Slf4j;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

/**
 * @author zhangsheng
 * @date 2021/8/3 11:15
 */
@Slf4j
public class BeanUtils {

    public static Map<String, Object> convert2Map(Object obj) {
        try {
            Map<String, Object> map = new HashMap<String, Object>();
            BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
            for (PropertyDescriptor property : propertyDescriptors) {
                String key = property.getName();
                if (key.compareToIgnoreCase("class") == 0) {
                    continue;
                }
                Method getter = property.getReadMethod();
                Object value = getter != null ? getter.invoke(obj) : null;
                map.put(key, value);
            }
            return map;
        } catch (Exception e) {
            log.warn("=convert2Map=>error:", e);
            throw new EventException(ExceptionEnum.CONVERT_2_MAP_ERROR, obj.getClass().getName());
        }
    }

    public static <T> T map2Bean(Map<String, Object> map, Class<T> clz) throws EventException {
        if (map == null) {
            return null;
        }
        try {
            Object obj = clz.newInstance();
            BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
            for (PropertyDescriptor property : propertyDescriptors) {
                Method setter = property.getWriteMethod();
                if (setter != null && null != map.get(property.getName()) &&
                        property.getPropertyType().isAssignableFrom(map.get(property.getName()).getClass())) {
                    setter.invoke(obj, map.get(property.getName()));
                }
            }
            return (T) obj;
        } catch (Exception e) {
            throw new EventException(ExceptionEnum.MAP_2_BEAN_ERROR, clz.getSimpleName());
        }
    }

    public static <T> T map2Bean(Map<String, Object> map, Object obj) throws Exception {
        if (map == null) {
            return null;
        }
        BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
        PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
        for (PropertyDescriptor property : propertyDescriptors) {
            Method setter = property.getWriteMethod();
            if (setter != null && null != map.get(property.getName()) &&
                    property.getPropertyType().isAssignableFrom(map.get(property.getName()).getClass())) {
                setter.invoke(obj, map.get(property.getName()));
            }
        }
        return (T) obj;
    }

}
